#include "iotgo_data_pool.h"
#include "iotgo_memory_hooks.h"
#include "iotgo_debug.h"
#include <stdlib.h>

#define debugPrint dataPoolDebugPrint

#define IDLE 0
#define USED 1

#define MAX_DATA_PACKAGE 3

typedef struct iotgoDataPool
{
    IOTGO_DATA_TYPE buf[MAX_DATA_PACKAGE];
    unsigned char flag[MAX_DATA_PACKAGE];
    signed char index_fifo[MAX_DATA_PACKAGE];
} IOTGO_DATA_POOL;

static IOTGO_DATA_POOL *pData = NULL;

signed char createIotgoDataPool(void)
{
    print_memory_heap();
    debugPrint("[%s]create iotgo data pool\n",__FUNCTION__);

    pData = (IOTGO_DATA_POOL *) pMalloc(sizeof(IOTGO_DATA_POOL));

    debugPrint("[%s] :sizeof(DataPool) is %d\n",__FUNCTION__,sizeof(IOTGO_DATA_POOL));
    if(!pData)
    {
	debugPrint("[%s] :create pool failed\n",__FUNCTION__);
	return IOTGO_DATA_POOL_FAIL;
    }
    
    print_memory_heap();
    memset(pData->buf,0,sizeof(IOTGO_DATA_POOL));
    memset(pData->flag,IDLE,MAX_DATA_PACKAGE);
    memset(pData->index_fifo,-1,MAX_DATA_PACKAGE);
    return 0;
}

signed char releaseIotgoDataPool(void)
{
    if(pData != NULL)
    {
	memset(pData,0,sizeof(pData));
	pFree(pData);
    }
    return 0;
}

static void addNumToIndexFifo(unsigned char num)
{
    unsigned char j = 0;
    for(j = 0; j < MAX_DATA_PACKAGE; j++)
    {
	if(pData->index_fifo[j] == -1) //find the last positon
	{
	    pData->index_fifo[j] = num;
	    break;
	}
    }
}

static void updateIndexFifo(unsigned char num)
{
    unsigned char j = num;
    for(j = num; j < MAX_DATA_PACKAGE -1 ; j++)
    {
	pData->index_fifo[j] = pData->index_fifo[j+1];
    }
    pData->index_fifo[MAX_DATA_PACKAGE - 1] = -1;
}


signed char writeToIotgoDataPool(IOTGO_DATA_TYPE *buf)
{
    unsigned char i = 0;

    if(!pData)
    {
        return IOTGO_DATA_POOL_FAIL;
    }

    for(i = 0; i < MAX_DATA_PACKAGE; i++)
    {
        if(pData->flag[i] == IDLE) //find a empty buf
        {
            /* store the data*/
            memcpy(&(pData->buf[i]),buf,sizeof(IOTGO_DATA_TYPE));
            /* update the index */
            addNumToIndexFifo(i);
            /* set flag*/
            pData->flag[i] = USED;
            return 0;
        }
    }

    return IOTGO_DATA_POOL_FAIL;
}


signed char readFromIotgoDataPool(unsigned char type, IOTGO_DATA_TYPE *buf)
{
    unsigned char i = 0;
    signed char buf_position = -1;

    debugPrint("[%s] user want type is %d\n",__FUNCTION__,type);
    
    if(!pData)
    {
	return IOTGO_DATA_POOL_FAIL;
    }
    
    debugPrint("[%s] check pData,it is inited\n",__FUNCTION__);
    
    for(i = 0; i < MAX_DATA_PACKAGE; i++)
    {
        debugPrint("[%s]data pool package num: %d\n",__FUNCTION__,i);
        debugPrint("[%s]index_fifo is %d\n",__FUNCTION__,pData->index_fifo[i]);
        /*check data by index,index == -1 means no data anymore.*/
        if(pData->index_fifo[i] != -1) 
        {
	    debugPrint("[%s]flag is %d\n",__FUNCTION__,pData->flag[(pData->index_fifo[i])]);
	    debugPrint("[%s]type is %d\n",__FUNCTION__,pData->buf[(pData->index_fifo[i])].type);
            buf_position = pData->index_fifo[i];
            //make sure there's data
            if(pData->flag[buf_position] == USED)
            {
                //find the right data
                if(pData->buf[buf_position].type == type)
                {
                    debugPrint("[%s] find the data\n",__FUNCTION__);
                    //copy the data to outside
                    memcpy(buf,&pData->buf[buf_position],sizeof(IOTGO_DATA_TYPE));
                    //update flag
                    pData->flag[buf_position] = IDLE;
                    //update index
                    updateIndexFifo(i);
                    return 0;
                }
                else
                {
                    debugPrint("[%s] data type does not match\n",__FUNCTION__);
                }
            }
            else
            {
                debugPrint("[%s] no data in current package:%d\n",__FUNCTION__,buf_position);
            }
        }
        else
        {
            debugPrint("[%s] no data in data pool\n",__FUNCTION__);
        }
    }
    
    return IOTGO_DATA_POOL_FAIL;
}

signed char cleanIotgoDataPool(void)
{
    if(pData != NULL)
    {
	memset(pData,0,sizeof(pData));
	memset(pData->index_fifo,-1,MAX_DATA_PACKAGE);
    }
    return 0;
}
